package core;

import android.util.Log;
import foc.physics.solver.GenericSolver;

import java.util.ArrayList;
import java.util.Stack;
import java.util.StringTokenizer;

import static core.Global.operations;
import static core.Global.values;

public class Formula {
    private ArrayList<String> variables = new ArrayList<String>();
    private ArrayList<String> formula = new ArrayList<String>();
    private String resultName;


    public Formula(String variables, String operators, String resultName) {
        StringTokenizer st = new StringTokenizer(variables, " ");
        while (st.hasMoreElements())
            this.variables.add(st.nextToken());

        st = new StringTokenizer(operators, " ");
        while (st.hasMoreElements())
            this.formula.add(st.nextToken());

        this.resultName = resultName;
    }

    public String works() {
        for (String s : variables)
            if (!values.containsKey(s))
                return null;
        return resultName;
    }

    /**
     * This is to be used when there are variables.
     *
     * @param genericSolver Reference to calling activity
     * @return The value of the expression
     */

    public Var evaluate(GenericSolver genericSolver) {
        Stack<Double> stack = new Stack<Double>();
        Var[] vars = new Var[2]; //Assuming that problems don't get more complex than 2 equations
        int count = 0;
        int sigFigs = Integer.MAX_VALUE;
        for (int i = 0; i < formula.size(); i++) {
            String s = formula.get(i);
            if (values.containsKey(s)) {
                Var var = values.get(s);
                if (var.sigFig < sigFigs)
                    sigFigs = var.sigFig;
                stack.push(var.value);
            } else if (s.equals("dup")) {
                stack.push(stack.peek());
            } else if (s.equals("poss")) {
                vars[count++] = new Var(resultName, stack.pop(), sigFigs);
            } else if (operations.containsKey(s)) {
                stack.push(operations.get(s).value(stack.pop(), stack.pop()));
            } else {
                stack.push(Double.parseDouble(s));
            }

        }
        vars[count++] = new Var(resultName, stack.pop(), sigFigs);
        if (count == 1) {
            if (stack.size() == 1)
                Log.d("Stack Size! ", "Error");
            return vars[0];
        } else {
            genericSolver.showDialog(resultName, vars[0], vars[1]);
            return null;
        }
    }

    /**
     * This is to be used when there are no variables. Significant figures are not accounted for.
     *
     * @return The value of the expression
     */

    public double freeEvaluate() {
        Stack<Double> stack = new Stack<Double>();
        for (String s : formula)
            if (operations.containsKey(s))
                stack.add(operations.get(s).value(stack.pop(), stack.pop()));
            else
                stack.add(Double.parseDouble(s));
        return stack.pop();
    }
}
